package com.base.cn.platform.os.service.op.affiche.tmp;

import com.base.cn.platform.os.common.constants.ConfigName;
import com.base.cn.platform.os.common.j2cache.CustomCacheChannel;
import com.base.cn.platform.os.common.j2cache.J2CacheRegion;
import com.base.cn.platform.os.common.msg.WXTmpEnum;
import com.base.cn.platform.os.common.utils.InputStreamUtil;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.user.ProfileType;
import com.base.cn.platform.os.common.utils.web.thirdLogin.WXLoginUtils;
import com.base.cn.platform.os.entity.op.affiche.OpReceiveAffiche;
import com.base.cn.platform.os.entity.user.user.CusUser;
import com.base.cn.platform.os.entity.user.user.CuserProfile;
import com.base.cn.platform.os.service.manage.config.SysConfigBiz;
import com.base.cn.platform.os.service.op.affiche.OpReceiveAfficheBiz;
import com.base.cn.platform.os.service.user.user.CuserProfileBiz;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;

import java.io.DataOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 模板发送消息抽象类（使用了模板模式）
 *
 * @author s.li
 * @date 2019/05/28
 */
@Slf4j
public abstract class SendTemAffice {
    private static Gson gson = new Gson();
    protected OpReceiveAfficheBiz receiveAfficheBiz;
    protected SysConfigBiz sysConfigBiz;
    protected CuserProfileBiz cuserProfileBiz;
    protected CustomCacheChannel customCacheChannel;
    protected TreeMap<String, String> smsTempConfigMap;
    protected static String SITE_MESSAGE_KEY ="site_message";
    protected static String WX_MESSAGE_KEY ="wx_message";
    protected static String MSG_TYPE ="msg_type";

    /**
     * 初始化服务对象
     * @param arr
     */
    public void initService(Object[] arr){
        this.receiveAfficheBiz = (OpReceiveAfficheBiz)arr[0];
        this.sysConfigBiz = (SysConfigBiz)arr[1];
        this.cuserProfileBiz = (CuserProfileBiz)arr[2];
        this.customCacheChannel = (CustomCacheChannel)arr[3];
        this.smsTempConfigMap = (TreeMap<String, String>)arr[4];
    }
    /**
     * 初始化消息内容
     * @param arr
     * @param tmpEnum 模板类型
     * @param userList 用户列表
     * @param dataListMap 业务数据
     * @return Map<String,String> 内容
     */
    public abstract Map<String,Object> initMsg(Object[] arr, WXTmpEnum tmpEnum, List<CusUser> userList, Map<BigDecimal,List> dataListMap);

    /**
     * 发送消息
     * @param arr
     * @param tmpEnum 模板类型
     * @param userList 用户列表
     * @param dataListMap 业务数据
     */
    public void sendMessage(Object[] arr,WXTmpEnum tmpEnum, List<CusUser> userList, Map<BigDecimal,List> dataListMap){
        //初始化消息内容
        Map<String,Object> msgMap = initMsg(arr,tmpEnum,userList,dataListMap);

        //通过返回的消息进行发送
        if(ObjectUtils.isNotEmpty(msgMap)){
            String msgType = (String)msgMap.get(MSG_TYPE);
            if(msgType.contains(MsgType.SITE.getKey())){//站内消息
                List<OpReceiveAffiche> receiveAfficheList = (List<OpReceiveAffiche>)msgMap.get(SITE_MESSAGE_KEY);
                if(ObjectUtils.isNotEmpty(receiveAfficheList)){
                    //批量发送站内消息
                    receiveAfficheBiz.batchSave(receiveAfficheList);
                }
            }
            if(msgType.contains(MsgType.WX.getKey())){//微信消息
                List<JSONObject> jsonObjectList = (List<JSONObject>)msgMap.get(WX_MESSAGE_KEY);
                if(ObjectUtils.isNotEmpty(jsonObjectList)){
                    //发送消息
                   this.sendWxMessage(jsonObjectList);
                }
            }
        }
    }

    /**
     * 发送微信消息
     * @param jsonObjectList
     */
    private void sendWxMessage(List<JSONObject> jsonObjectList){
        try{
            TreeMap<String,String> config = sysConfigBiz.getSysConfigContext(ConfigName.WXLOGIN);
            String appId = config.get("appId");
            String appSecret = config.get("appSecret");
            //获取微信accessToken
            String accessToken = WXLoginUtils.getOpenAccessToken(appId,appSecret,customCacheChannel);
            URL url = new URL("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+accessToken);
            jsonObjectList.forEach(data->{
                //发送请求
                String result;
                try {
                    result = this.request(url,data.toString());
                    Thread.sleep(100);
                } catch (Exception e) {
                    throw new RuntimeException("sendWxMessage()--error",e);
                }
                //解析返回结果
                log.info("----------------result:"+result);
                //删除模板
                String templateId = data.getString("template_id");
                this.deleteTemp(templateId);
            });
        }catch (Exception e){
            log.error("sendWxMessage()--error",e);
            throw new RuntimeException("sendWxMessage()--error",e);
        }
    }

    /**
     * 删除无效模板
     * @param templateId 模板ID
     */
    private void deleteTemp(String templateId){
        try{
            TreeMap<String,String> config = sysConfigBiz.getSysConfigContext(ConfigName.WXLOGIN);
            String appId = config.get("appId");
            String appSecret = config.get("appSecret");
            String accessToken = WXLoginUtils.getOpenAccessToken(appId,appSecret,customCacheChannel);
            JSONObject obj = new JSONObject();
            obj.put("template_id",templateId);
            URL url = new URL("https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token="+accessToken);
            String result = this.request(url,obj.toString());
            log.info("=================>delete result:"+result);
        }catch (Exception e){
            log.error("deleteTemp()--->",e);
        }
    }

    /***
     * 获取微信消息模板
     * @param tmpEnum 类型数据
     * @return 模板ID
     */
    protected String getTmpId(WXTmpEnum tmpEnum){
        //从缓存获取，如果缓存不存在再从微信中获取数据
        String tmpId;
        try {
            TreeMap<String,String> config = sysConfigBiz.getSysConfigContext(ConfigName.WXLOGIN);
            String appId = config.get("appId");
            String appSecret = config.get("appSecret");
            String accessToken = WXLoginUtils.getOpenAccessToken(appId,appSecret,customCacheChannel);
            if(accessToken==null){
                throw new RuntimeException("获取微信Token失败-->{}"+tmpEnum.getIdNo());
            }
            JSONObject obj = new JSONObject();
            obj.put("template_id_short", tmpEnum.getIdNo());
            URL url = new URL("https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token="+accessToken);
            //发送请求
            String result = this.request(url,obj.toString());
            Map<String,Object> resultMap = gson.fromJson(result,Map.class);
            tmpId = (String) resultMap.get("template_id");
            if(tmpId !=null){
                return tmpId;
            }else{
                throw new RuntimeException("获取微信消息模板ID失败-->{}"+tmpEnum.getIdNo());
            }
        } catch (Exception e) {
            log.error("获取微信消息模板ID失败-->{}"+tmpEnum.getIdNo(),e);
            throw new RuntimeException("获取微信消息模板ID失败-->{}"+tmpEnum.getIdNo(),e);
        }
    }

    /**
     * 发送请求
     * @param url
     * @param jsonParams
     * @return
     * @throws Exception
     */
    private String request(URL url,String jsonParams) throws Exception{
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type","application/json;charset=UTF-8;");
        DataOutputStream out = new DataOutputStream(conn.getOutputStream());
        out.write(jsonParams.getBytes());
        out.flush();
        out.close();
        InputStream inStream = conn.getInputStream();
        String result = new String(InputStreamUtil.readInputStream(inStream), "utf-8");
        return result;
    }

    /**
     * 设置消息备注内容
     * @param data
     * @param remark
     */
    public void setRemarkMap(Map<String,Map<String,String>> data,String remark){
        //消息备注
        if(StringUtils.isNotEmpty(remark)){
            Map<String,String> remarkMap = new HashMap<>();
            remarkMap.put("value",remark);
            remarkMap.put("color","#173177");
            data.put("remark",remarkMap);
        }
    }

    /**
     * 获取用户第三方登录数据列表
     * @param userList 用户列表
     * @return List<CuserProfile>
     */
    public List<CuserProfile> getCuserProfileList(List<CusUser> userList){
        String userIds = userList.stream().map(e->e.getId().toString()).collect(Collectors.joining(","));
        List<CuserProfile> cuserProfileList = cuserProfileBiz.find("profileType = '"+ ProfileType.WEIXIN.toString() +"' and userId in ("+userIds+") and openId is not null and openId !=''",null, Arrays.asList("openId","userId"));
        return cuserProfileList;
    }
}
